package com.ma.a05;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.type.MethodMetadata;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;

import java.io.IOException;
import java.util.Set;

/**
 * @ClassName AtBeanPostProcessor
 * @Author: mayongqiang
 * @DATE 2022/4/1 20:58
 * @Description:
 */

public class AtBeanPostProcessor implements BeanFactoryPostProcessor {
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
        // 拿到Config.class中被@Bean标注的信息
        MetadataReader reader = null;
        try {
            reader = factory.getMetadataReader(new ClassPathResource("com/ma/a05/Config.class"));
        } catch (IOException e) {
            e.printStackTrace();
        }
        Set<MethodMetadata> methods = reader.getAnnotationMetadata().getAnnotatedMethods(Bean.class.getName());
        for (MethodMetadata method : methods) {
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition();

            String initMethod = method.getAnnotationAttributes(Bean.class.getName()).get("initMethod").toString();
            if (initMethod.length() > 0) {
                builder.setInitMethodName(initMethod);
            }


            builder.setFactoryMethodOnBean(method.getMethodName(), "config");
            builder.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR);

            AbstractBeanDefinition bd = builder.getBeanDefinition();
            DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
            beanFactory.registerBeanDefinition(method.getMethodName(), bd);

        }
    }
}
